package com.ddxz.tool.core.convert;

import com.ddxz.tool.core.exception.DdxzBaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.util.*;
import java.util.stream.Collectors;

import static com.ddxz.tool.core.exception.DdxzErrorStatus.ARRAY_LENGTH_ERROR;
import static com.ddxz.tool.core.exception.DdxzErrorStatus.CONSTRUCTOR_NOT_FOUND;

/**
 * @author 朱宗刚
 * @version 1.0.0
 * @description com.casic.exchange.com.casic.common.tools.convert.CollectionUtil
 * @date 2020/2/28
 */

public class CollectionUtil {
    private static final Logger log = LoggerFactory.getLogger(CollectionUtil.class);

    public static <T> boolean isEmpty(Collection<T> colls) {
        return colls == null || colls.isEmpty();
    }

    public static <K, V> boolean isEmpty(Map<K, V> maps) {
        return maps == null || maps.isEmpty();
    }

    public static <T> boolean isEmpty(T[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(byte[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(int[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(long[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(boolean[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(short[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(char[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(float[] arr) {
        return arr == null || arr.length < 1;
    }

    public static boolean isEmpty(double[] arr) {
        return arr == null || arr.length < 1;
    }

    /**
     * @param list1 集合1
     * @param list2 集合2
     * @return 计算集合1与集合2的并集（list1 ∪  list2）
     */
    public static <T> List<T> unionAll(List<T> list1, List<T> list2) {
        list1.addAll(list2);

        return list1;
    }

    public static byte[] resize(byte[] bytes, int newSize) {
        if(newSize < 0){
            return bytes;
        }
        final byte[] newArray = new byte[newSize];
        if (newSize > 0 && !isEmpty(bytes)) {
            System.arraycopy(bytes, 0, newArray, 0, Math.min(bytes.length, newSize));
        }
        return newArray;
    }

    /**
     * @param list1 集合1
     * @param list2 集合2
     * @return 计算集合1与集合2的去重并集（list1 ∪ list2）
     */
    public static <T> List<T> union(List<T> list1, List<T> list2) {
        list1.addAll(list2);
        return list1.parallelStream().distinct().collect(Collectors.toList());
    }

    /**
     * @param list1 集合1
     * @param list2 集合2
     * @return 计算集合1与集合2的差集（list1 - list2）
     */
    public static <T> List<T> except(List<T> list1, List<T> list2) {
        Set<T> var2 = new HashSet<>(list2);
        return list1.parallelStream().filter(item->!var2.contains(item)).collect(Collectors.toList());
    }

    /**
     * @param list1 集合1
     * @param list2 集合2
     * @return 计算集合1与集合2的差集（list1 - list2）
     */
    public static <T> Set<T> except(Set<T> list1, Set<T> list2) {
        return list1.parallelStream().filter(item -> !list2.contains(item)).collect(Collectors.toSet());
    }

    /**
     * @param list1 集合1
     * @param list2 集合2
     * @return 计算集合1与集合2的交集（list1 ∩ list2）
     */
    public static <T> List<T> intersect(List<T> list1, List<T> list2) {
        Set<T> tmp = new HashSet<>(list2);
        return list1.parallelStream().filter(item -> tmp.contains(item)).collect(Collectors.toList());
    }

    /**
     * @param list1 集合1
     * @param list2 集合2
     * @return 计算集合1与集合2的交集（list1 ∩ list2）
     */
    public static <T> Set<T> intersect(Set<T> list1, Set<T> list2) {
        return list1.parallelStream().filter(item -> list2.contains(item)).collect(Collectors.toSet());
    }

    public static <S> void copyCollection(Collection<S> src, Collection<Object> tar, Class<?> cla) {
        copyCollection(src, tar, cla, DdxzUtil.NONE_CONVERT);
    }

    public static <S> void copyCollection(Collection<S> src, Collection<Object> tar, Class<?> cla, int type) {
        if(isEmpty(src) || tar == null) {
            return;
        }

        try {
            Constructor<Object> constructor = (Constructor<Object>) cla.getConstructor();
            Object t;
            for(S s : src) {
                t = constructor.newInstance();
                BeanUtil.copyProperties(s, t, type);
                tar.add(t);
            }
        } catch (Exception e) {
            log.error(CONSTRUCTOR_NOT_FOUND.getMessage(), e);
            throw new DdxzBaseException(CONSTRUCTOR_NOT_FOUND);
        }
    }

    public static <S, T> void copyCollection(S[] src, T[] tar, Class<T> cla) {
        copyCollection(src, tar, cla, DdxzUtil.NONE_CONVERT);
    }

    public static <S, T> void copyCollection(S[] src, T[] tar, Class<T> cla, int type) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        T t;
        try{
            Constructor<T> constructor = cla.getConstructor();
            int idx = 0;
            for(S s : src) {
                t = constructor.newInstance();
                BeanUtil.copyProperties(s, t,type);
                tar[idx++] = t;
            }
        } catch (Exception e) {
            log.error(CONSTRUCTOR_NOT_FOUND.getMessage(), e);
            throw new DdxzBaseException(CONSTRUCTOR_NOT_FOUND);
        }
    }

    public static <T> void copyCollection(T[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(T t : src) {
            tar[idx++] = t.toString();
        }
    }

    public static void copyCollection(int[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(int s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(int[] src, String[] tar, boolean version) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(int s : src) {
            tar[idx++] = VersionUtil.verToStr(s);
        }
    }

    public static void copyCollection(char[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(char s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(short[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(short s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(long[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(long s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(long[] src, String[] tar, int timestamp) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        switch (timestamp & DdxzUtil.DATE_CONVERT) {
            case DdxzUtil.MILLISEC_DATE:
                for (long s : src) {
                    tar[idx++] = DateUtil.toCvtDate(s);
                }
                return;
            case DdxzUtil.MILLISEC_DATETIME:
                for (long s : src) {
                    tar[idx++] = DateUtil.toCvtDateTime(s);
                }
                return;
            case DdxzUtil.MILLISEC_TIME:
                for (long s : src) {
                    tar[idx++] = DateUtil.toCvtTime(s);
                }
                return;
            case DdxzUtil.SECOND_DATE:
                for (long s : src) {
                    tar[idx++] = DateUtil.toStdDate(s);
                }
                return;
            case DdxzUtil.SECOND_DATETIME:
                for (long s : src) {
                    tar[idx++] = DateUtil.toStdDateTime(s);
                }
                return;
            case DdxzUtil.SECOND_TIME:
                for (long s : src) {
                    tar[idx++] = DateUtil.toStdTime(s);
                }
                return;
            default:
                for (long s : src) {
                    tar[idx++] = String.valueOf(s);
                }
        }
    }

    public static void copyCollection(float[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(float s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(double[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(double s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(byte[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(byte s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(boolean[] src, String[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(boolean s : src) {
            tar[idx++] = String.valueOf(s);
        }
    }

    public static void copyCollection(String[] src, float[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Float.parseFloat(s);
        }
    }

    public static void copyCollection(String[] src, double[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Double.parseDouble(s);
        }
    }

    public static void copyCollection(String[] src, byte[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Byte.parseByte(s);
        }
    }

    public static void copyCollection(String[] src, boolean[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Boolean.parseBoolean(s);
        }
    }

    public static void copyCollection(String[] src, char[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = StringUtil.isEmpty(s) ? 0 : s.charAt(0);
        }
    }

    public static void copyCollection(String[] src, short[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Short.parseShort(s);
        }
    }

    public static void copyCollection(String[] src, long[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Long.parseLong(s);
        }
    }

    public static void copyCollection(String[] src, int[] tar) {
        if(isEmpty(src)) {
            return;
        }

        if(src.length != tar.length) {
            throw new DdxzBaseException(ARRAY_LENGTH_ERROR, src.length, tar.length);
        }

        int idx = 0;
        for(String s : src) {
            tar[idx++] = Integer.parseInt(s);
        }
    }
}
